package cn.tedu.csmall.passport.filter;

import cn.tedu.csmall.commons.security.CurrentPrincipal;
import cn.tedu.csmall.commons.web.JsonResult;
import cn.tedu.csmall.commons.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.*;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;

@Slf4j
@Component
public class JwtAuthorizationFilter extends OncePerRequestFilter {
    @Value("${csmall.jwt.key}")
    private String key;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        log.debug("JwtAuthorizationFilter开始执行");
        // 根据业内惯用的做法，客户端会将JWT放在请求头（Request Header）中的Authorization属性中

        String jwt=request.getHeader("Authorization");
        log.debug("客户端携带的Jwt：{}",jwt);

        //判断客户端是否携带了有效的JWT
        if(!StringUtils.hasText(jwt)){
            filterChain.doFilter(request,response);
            return;
        }
        //解析Jwt
        //String key="fhjkahfjkdahfjka2365465fjagdjkaddAEDFSD";
        Claims claims=null;
        response.setContentType("application/json;charset=UTF-8");
        try{
            claims = Jwts.parser().setSigningKey(key)
                    .parseClaimsJws(jwt).getBody();

        } catch (MalformedJwtException e){
            String message="小黑子，别再黑辣！";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_MALFORMED, message);
            String jsonString = JSON.toJSONString(jsonResult);
            PrintWriter printWriter=response.getWriter();
            printWriter.println(jsonString);
            printWriter.close();
            return;
        }catch (SignatureException e){
            String message="小黑子，再黑我就紫砂辣！";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_SIGNATURE, message);
            String jsonString = JSON.toJSONString(jsonResult);
            PrintWriter printWriter=response.getWriter();
            printWriter.println(jsonString);
            printWriter.close();
            return;
        }catch (ExpiredJwtException e){
            String message="您的凭证已过期";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_EXPIRED, message);
            String jsonString = JSON.toJSONString(jsonResult);
            PrintWriter printWriter=response.getWriter();
            printWriter.println(jsonString);
            printWriter.close();
            return;
        }catch (Throwable e){
            String message="出现了未知的错误";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_UNKNOWN, message);
            String jsonString = JSON.toJSONString(jsonResult);
            PrintWriter printWriter=response.getWriter();
            printWriter.println(jsonString);
            printWriter.close();
            return;
        }
        Long id = claims.get("id",Long.class);
        String username = claims.get("username",String.class);
        String authority = claims.get("authorities", String.class);

        log.debug("id:{},username:{}",id,username);

        //创建当事人数据
        CurrentPrincipal currentPrincipal=new CurrentPrincipal();
        currentPrincipal.setId(id);
        currentPrincipal.setUsername(username);
        //创建认证信息
        Object principal=currentPrincipal;
        Object credentials=null;
        Collection<SimpleGrantedAuthority> authorities=
                JSON.parseArray(authority, SimpleGrantedAuthority.class);
        Authentication authentication= new UsernamePasswordAuthenticationToken(principal,credentials,authorities);

        // 将认证信息存入到SecurityContext中
        SecurityContext context = SecurityContextHolder.getContext();
        context.setAuthentication(authentication);

        //放行
        filterChain.doFilter(request,response);
    }
}
